package com.itheima.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.itheima.model.common.dtos.ResponseResult;
import com.itheima.model.common.enums.AppHttpCodeEnum;
import com.itheima.model.search.dtos.BookSearchDto;
import com.itheima.search.service.BookSearchService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class BookSearchServiceImpl implements BookSearchService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 搜索图书
     * @param dto
     * @return
     */
    @Override
    public ResponseResult search(BookSearchDto dto) {
        //1.检查参数
        if (dto == null || StringUtils.isBlank(dto.getKw())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        try {
            //2.设置查询条件
            SearchRequest searchRequest = new SearchRequest("book"); // 图书索引名称
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            //布尔查询构建器
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

            //关键字分词查询：对标题、作者、描述字段进行搜索
            QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders
                    .queryStringQuery(dto.getKw())
                    .field("title", 3.0f)  // 标题权重更高
                    .field("author", 2.0f) // 作者权重次之
                    .field("description")  // 描述默认权重
                    .defaultOperator(Operator.OR); // 多个关键词满足其一即可
            boolQueryBuilder.must(queryStringQueryBuilder);

            //分页处理
            int page = dto.getPage();
            int size = dto.getSize();
            int from = (page - 1) * size;
            searchSourceBuilder.from(from);
            searchSourceBuilder.size(size);

            //设置高亮：高亮标题字段
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("title");
            highlightBuilder.preTags("<font style='color:red; font-size: inherit'>");
            highlightBuilder.postTags("</font>");
            searchSourceBuilder.highlighter(highlightBuilder);

            //设置查询条件
            searchSourceBuilder.query(boolQueryBuilder);
            searchRequest.source(searchSourceBuilder);

            //执行查询
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            //3.结果封装
            List<Map> bookList = new ArrayList<>();
            SearchHit[] hits = searchResponse.getHits().getHits();
            for (SearchHit hit : hits) {
                //解析原始数据
                String json = hit.getSourceAsString();
                Map<String, Object> bookMap = JSON.parseObject(json, Map.class);

                //处理高亮标题
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                if (highlightFields != null && highlightFields.containsKey("title")) {
                    Text[] titleFragments = highlightFields.get("title").getFragments();
                    String highlightTitle = StringUtils.join(titleFragments);
                    bookMap.put("h_title", highlightTitle); // 高亮标题放入h_title字段
                } else {
                    bookMap.put("h_title", bookMap.get("title")); // 无高亮时使用原始标题
                }

                bookList.add(bookMap);
            }

            //返回结果，可根据需要封装分页信息
            return ResponseResult.okResult(bookList);

        } catch (IOException e) {
            log.error("图书搜索失败", e);
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "搜索失败");
        }
    }

}
